/*
 * Copyright (c) 2022, IMMORTA Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * - Neither the name of IMMORTA Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef CAN_REG_ACCESS_H
#define CAN_REG_ACCESS_H

/*!
 * @file can_reg_access.h
 * @brief This file declares or defines can register access functions
 */

/*******Includes***************************************************************/
#include "can_drv.h"

/*******Definitions************************************************************/

/* =========================================================  RBUFF  ========================================================= */
/* =======================================================  ID&ESI  ========================================================== */
#define CAN_RBUFF_ID_STD(x)               (((uint32_t)(((uint32_t)(x)) << CAN_RBUFF_ID_STD_Pos)) & CAN_RBUFF_ID_STD_Msk)
#define CAN_RBUFF_ID_EXT(x)               (((uint32_t)(((uint32_t)(x)) << CAN_RBUFF_ID_EXT_Pos)) & CAN_RBUFF_ID_EXT_Msk)
#define CAN_RBUFF_ESI(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_RBUFF_ESI_Pos)) & CAN_RBUFF_ESI_Msk)
/* =======================================================  CONTROL&STATUS  ================================================== */
#define CAN_RBUFF_DLC(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_RBUFF_DLC_Pos)) & CAN_RBUFF_DLC_Msk)
#define CAN_RBUFF_BRS(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_RBUFF_BRS_Pos)) & CAN_RBUFF_BRS_Msk)
#define CAN_RBUFF_FDF(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_RBUFF_FDF_Pos)) & CAN_RBUFF_FDF_Msk)
#define CAN_RBUFF_RTR(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_RBUFF_RTR_Pos)) & CAN_RBUFF_RTR_Msk)
#define CAN_RBUFF_IDE(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_RBUFF_IDE_Pos)) & CAN_RBUFF_IDE_Msk)
#define CAN_RBUFF_TX(x)                   (((uint32_t)(((uint32_t)(x)) << CAN_RBUFF_TX_Pos)) & CAN_RBUFF_TX_Msk)
#define CAN_RBUFF_KOER(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_RBUFF_KOER_Pos)) & CAN_RBUFF_KOER_Msk)
/* =========================================================  TBUFF  ========================================================= */
/* =======================================================  ID&TTSEN  ======================================================== */
#define CAN_TBUFF_ID_STD(x)               (((uint32_t)(((uint32_t)(x)) << CAN_TBUFF_ID_STD_Pos)) & CAN_TBUFF_ID_STD_Msk)
#define CAN_TBUFF_ID_EXT(x)               (((uint32_t)(((uint32_t)(x)) << CAN_TBUFF_ID_EXT_Pos)) & CAN_TBUFF_ID_EXT_Msk)
#define CAN_TBUFF_TTSEN(x)                (((uint32_t)(((uint32_t)(x)) << CAN_TBUFF_TTSEN_Pos)) & CAN_TBUFF_TTSEN_Msk)
/* =======================================================  CONTROL&STATUS  ================================================== */
#define CAN_TBUFF_DLC(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_TBUFF_DLC_Pos)) & CAN_TBUFF_DLC_Msk)
#define CAN_TBUFF_BRS(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_TBUFF_BRS_Pos)) & CAN_TBUFF_BRS_Msk)
#define CAN_TBUFF_FDF(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_TBUFF_FDF_Pos)) & CAN_TBUFF_FDF_Msk)
#define CAN_TBUFF_RTR(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_TBUFF_RTR_Pos)) & CAN_TBUFF_RTR_Msk)
#define CAN_TBUFF_IDE(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_TBUFF_IDE_Pos)) & CAN_TBUFF_IDE_Msk)
/* =========================================================  CTRL0  ========================================================= */
#define CAN_CTRL0_BUSOFF(x)               (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_BUSOFF_Pos)) & CAN_CTRL0_BUSOFF_Msk)
#define CAN_CTRL0_TACTIVE(x)              (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_TACTIVE_Pos)) & CAN_CTRL0_TACTIVE_Msk)
#define CAN_CTRL0_RACTIVE(x)              (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_RACTIVE_Pos)) & CAN_CTRL0_RACTIVE_Msk)
#define CAN_CTRL0_TSSS(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_TSSS_Pos)) & CAN_CTRL0_TSSS_Msk)
#define CAN_CTRL0_TPSS(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_TPSS_Pos)) & CAN_CTRL0_TPSS_Msk)
#define CAN_CTRL0_LBMI(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_LBMI_Pos)) & CAN_CTRL0_LBMI_Msk)
#define CAN_CTRL0_LBME(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_LBME_Pos)) & CAN_CTRL0_LBME_Msk)
#define CAN_CTRL0_RESET(x)                (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_RESET_Pos)) & CAN_CTRL0_RESET_Msk)
#define CAN_CTRL0_TSA(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_TSA_Pos)) & CAN_CTRL0_TSA_Msk)
#define CAN_CTRL0_TSALL(x)                (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_TSALL_Pos)) & CAN_CTRL0_TSALL_Msk)
#define CAN_CTRL0_TSONE(x)                (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_TSONE_Pos)) & CAN_CTRL0_TSONE_Msk)
#define CAN_CTRL0_TPA(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_TPA_Pos)) & CAN_CTRL0_TPA_Msk)
#define CAN_CTRL0_TPE(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_TPE_Pos)) & CAN_CTRL0_TPE_Msk)
#define CAN_CTRL0_STBY(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_STBY_Pos)) & CAN_CTRL0_STBY_Msk)
#define CAN_CTRL0_LOM(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_LOM_Pos)) & CAN_CTRL0_LOM_Msk)
#define CAN_CTRL0_TBSEL(x)                (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_TBSEL_Pos)) & CAN_CTRL0_TBSEL_Msk)
#define CAN_CTRL0_TSSTAT(x)               (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_TSSTAT_Pos)) & CAN_CTRL0_TSSTAT_Msk)
#define CAN_CTRL0_BOFFREC(x)              (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_BOFFREC_Pos)) & CAN_CTRL0_BOFFREC_Msk)
#define CAN_CTRL0_CANFDEN(x)              (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_CANFDEN_Pos)) & CAN_CTRL0_CANFDEN_Msk)
#define CAN_CTRL0_TSMODE(x)               (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_TSMODE_Pos)) & CAN_CTRL0_TSMODE_Msk)
#define CAN_CTRL0_TSNEXT(x)               (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_TSNEXT_Pos)) & CAN_CTRL0_TSNEXT_Msk)
#define CAN_CTRL0_FDISO(x)                (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_FDISO_Pos)) & CAN_CTRL0_FDISO_Msk)
#define CAN_CTRL0_RSTAT(x)                (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_RSTAT_Pos)) & CAN_CTRL0_RSTAT_Msk)
#define CAN_CTRL0_RBALL(x)                (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_RBALL_Pos)) & CAN_CTRL0_RBALL_Msk)
#define CAN_CTRL0_RREL(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_RREL_Pos)) & CAN_CTRL0_RREL_Msk)
#define CAN_CTRL0_ROV(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_ROV_Pos)) & CAN_CTRL0_ROV_Msk)
#define CAN_CTRL0_ROM(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_ROM_Pos)) & CAN_CTRL0_ROM_Msk)
#define CAN_CTRL0_SACK(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL0_SACK_Pos)) & CAN_CTRL0_SACK_Msk)
/* =========================================================  CTRL1  ========================================================= */
#define CAN_CTRL1_TSFF(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_TSFF_Pos)) & CAN_CTRL1_TSFF_Msk)
#define CAN_CTRL1_EIE(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_EIE_Pos)) & CAN_CTRL1_EIE_Msk)
#define CAN_CTRL1_TSIE(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_TSIE_Pos)) & CAN_CTRL1_TSIE_Msk)
#define CAN_CTRL1_TPIE(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_TPIE_Pos)) & CAN_CTRL1_TPIE_Msk)
#define CAN_CTRL1_RAFIE(x)                (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_RAFIE_Pos)) & CAN_CTRL1_RAFIE_Msk)
#define CAN_CTRL1_RFIE(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_RFIE_Pos)) & CAN_CTRL1_RFIE_Msk)
#define CAN_CTRL1_ROIE(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_ROIE_Pos)) & CAN_CTRL1_ROIE_Msk)
#define CAN_CTRL1_RIE(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_RIE_Pos)) & CAN_CTRL1_RIE_Msk)
#define CAN_CTRL1_AIF(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_AIF_Pos)) & CAN_CTRL1_AIF_Msk)
#define CAN_CTRL1_EIF(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_EIF_Pos)) & CAN_CTRL1_EIF_Msk)
#define CAN_CTRL1_TSIF(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_TSIF_Pos)) & CAN_CTRL1_TSIF_Msk)
#define CAN_CTRL1_TPIF(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_TPIF_Pos)) & CAN_CTRL1_TPIF_Msk)
#define CAN_CTRL1_RAFIF(x)                (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_RAFIF_Pos)) & CAN_CTRL1_RAFIF_Msk)
#define CAN_CTRL1_RFIF(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_RFIF_Pos)) & CAN_CTRL1_RFIF_Msk)
#define CAN_CTRL1_ROIF(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_ROIF_Pos)) & CAN_CTRL1_ROIF_Msk)
#define CAN_CTRL1_RIF(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_RIF_Pos)) & CAN_CTRL1_RIF_Msk)
#define CAN_CTRL1_BEIF(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_BEIF_Pos)) & CAN_CTRL1_BEIF_Msk)
#define CAN_CTRL1_BEIE(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_BEIE_Pos)) & CAN_CTRL1_BEIE_Msk)
#define CAN_CTRL1_ALIF(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_ALIF_Pos)) & CAN_CTRL1_ALIF_Msk)
#define CAN_CTRL1_ALIE(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_ALIE_Pos)) & CAN_CTRL1_ALIE_Msk)
#define CAN_CTRL1_EPIF(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_EPIF_Pos)) & CAN_CTRL1_EPIF_Msk)
#define CAN_CTRL1_EPIE(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_EPIE_Pos)) & CAN_CTRL1_EPIE_Msk)
#define CAN_CTRL1_EPASS(x)                (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_EPASS_Pos)) & CAN_CTRL1_EPASS_Msk)
#define CAN_CTRL1_EWARN(x)                (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_EWARN_Pos)) & CAN_CTRL1_EWARN_Msk)
#define CAN_CTRL1_EWL(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_EWL_Pos)) & CAN_CTRL1_EWL_Msk)
#define CAN_CTRL1_AFWL(x)                 (((uint32_t)(((uint32_t)(x)) << CAN_CTRL1_AFWL_Pos)) & CAN_CTRL1_AFWL_Msk)
/* =======================================================  SBITRATE  ======================================================== */
#define CAN_SBITRATE_S_SEG_1(x)           (((uint32_t)(((uint32_t)(x)) << CAN_SBITRATE_S_SEG_1_Pos)) & CAN_SBITRATE_S_SEG_1_Msk)
#define CAN_SBITRATE_S_SEG_2(x)           (((uint32_t)(((uint32_t)(x)) << CAN_SBITRATE_S_SEG_2_Pos)) & CAN_SBITRATE_S_SEG_2_Msk)
#define CAN_SBITRATE_S_SJW(x)             (((uint32_t)(((uint32_t)(x)) << CAN_SBITRATE_S_SJW_Pos)) & CAN_SBITRATE_S_SJW_Msk)
#define CAN_SBITRATE_S_PRESC(x)           (((uint32_t)(((uint32_t)(x)) << CAN_SBITRATE_S_PRESC_Pos)) & CAN_SBITRATE_S_PRESC_Msk)
/* =======================================================  FBITRATE  ======================================================== */
#define CAN_FBITRATE_f_SEG_1(x)           (((uint32_t)(((uint32_t)(x)) << CAN_FBITRATE_f_SEG_1_Pos)) & CAN_FBITRATE_f_SEG_1_Msk)
#define CAN_FBITRATE_f_SEG_2(x)           (((uint32_t)(((uint32_t)(x)) << CAN_FBITRATE_f_SEG_2_Pos)) & CAN_FBITRATE_f_SEG_2_Msk)
#define CAN_FBITRATE_f_SJW(x)             (((uint32_t)(((uint32_t)(x)) << CAN_FBITRATE_f_SJW_Pos)) & CAN_FBITRATE_f_SJW_Msk)
#define CAN_FBITRATE_f_PRESC(x)           (((uint32_t)(((uint32_t)(x)) << CAN_FBITRATE_f_PRESC_Pos)) & CAN_FBITRATE_f_PRESC_Msk)
/* ========================================================  ERRINFO  ======================================================== */
#define CAN_ERRINFO_ALC(x)                (((uint32_t)(((uint32_t)(x)) << CAN_ERRINFO_ALC_Pos)) & CAN_ERRINFO_ALC_Msk)
#define CAN_ERRINFO_KOER(x)               (((uint32_t)(((uint32_t)(x)) << CAN_ERRINFO_KOER_Pos)) & CAN_ERRINFO_KOER_Msk)
#define CAN_ERRINFO_SSPOFF(x)             (((uint32_t)(((uint32_t)(x)) << CAN_ERRINFO_SSPOFF_Pos)) & CAN_ERRINFO_SSPOFF_Msk)
#define CAN_ERRINFO_TDCEN(x)              (((uint32_t)(((uint32_t)(x)) << CAN_ERRINFO_TDCEN_Pos)) & CAN_ERRINFO_TDCEN_Msk)
#define CAN_ERRINFO_RECNT(x)              (((uint32_t)(((uint32_t)(x)) << CAN_ERRINFO_RECNT_Pos)) & CAN_ERRINFO_RECNT_Msk)
#define CAN_ERRINFO_TECNT(x)              (((uint32_t)(((uint32_t)(x)) << CAN_ERRINFO_TECNT_Pos)) & CAN_ERRINFO_TECNT_Msk)
/* ========================================================  ACFCTRL0  ======================================================= */
#define CAN_ACFCTRL0_ACFADR(x)             (((uint32_t)(((uint32_t)(x)) << CAN_ACFCTRL0_ACFADR_Pos)) & CAN_ACFCTRL0_ACFADR_Msk)
#define CAN_ACFCTRL0_SELMASK(x)            (((uint32_t)(((uint32_t)(x)) << CAN_ACFCTRL0_SELMASK_Pos)) & CAN_ACFCTRL0_SELMASK_Msk)
#define CAN_ACFCTRL0_TIMEEN(x)             (((uint32_t)(((uint32_t)(x)) << CAN_ACFCTRL0_TIMEEN_Pos)) & CAN_ACFCTRL0_TIMEEN_Msk)
#define CAN_ACFCTRL0_TIMEPOS(x)            (((uint32_t)(((uint32_t)(x)) << CAN_ACFCTRL0_TIMEPOS_Pos)) & CAN_ACFCTRL0_TIMEPOS_Msk)
#define CAN_ACFCTRL0_ACFEN0(x)             (((uint32_t)(((uint32_t)(x)) << CAN_ACFCTRL0_ACFEN0_Pos)) & CAN_ACFCTRL0_ACFEN0_Msk)
/* ========================================================  ACFCTRL1  ======================================================= */
#define CAN_ACFCTRL1_ACFEN1(x)              (((uint32_t)(((uint32_t)(x)) << CAN_ACFCTRL1_ACFEN1_Pos)) & CAN_ACFCTRL1_ACFEN1_Msk)
/* ==========================================================  ACF  ========================================================== */
#define CAN_ACF_ACODE(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_ACF_ACODE_Pos)) & CAN_ACF_ACODE_Msk)
#define CAN_ACF_AIDE(x)                   (((uint32_t)(((uint32_t)(x)) << CAN_ACF_AIDE_Pos)) & CAN_ACF_AIDE_Msk)
#define CAN_ACF_AIDEE(x)                  (((uint32_t)(((uint32_t)(x)) << CAN_ACF_AIDEE_Pos)) & CAN_ACF_AIDEE_Msk)
/* ========================================================  VERSION  ======================================================== */
#define CAN_VERSION_VERSION(x)            (((uint32_t)(((uint32_t)(x)) << CAN_VERSION_VERSION_Pos)) & CAN_VERSION_VERSION_Msk)


#define CAN_INT_EN_Msk                    (CAN_CTRL1_EIE_Msk | CAN_CTRL1_TSIE_Msk | CAN_CTRL1_TPIE_Msk | CAN_CTRL1_RAFIE_Msk \
                                          | CAN_CTRL1_RFIE_Msk | CAN_CTRL1_ROIE_Msk | CAN_CTRL1_RIE_Msk | CAN_CTRL1_BEIE_Msk \
                                          | CAN_CTRL1_ALIE_Msk | CAN_CTRL1_EPIE_Msk)
#define CAN_INT_FLAG_Msk                  (CAN_CTRL1_TSFF_Msk | CAN_CTRL1_AIF_Msk | CAN_CTRL1_EIF_Msk | CAN_CTRL1_TSIF_Msk \
                                          | CAN_CTRL1_TPIF_Msk | CAN_CTRL1_RAFIF_Msk | CAN_CTRL1_RFIF_Msk | CAN_CTRL1_ROIF_Msk \
                                          | CAN_CTRL1_RIF_Msk | CAN_CTRL1_BEIF_Msk | CAN_CTRL1_ALIF_Msk | CAN_CTRL1_EPIF_Msk)

/*!
 * @brief CAN STB Transmit mode
 */
typedef enum {
    CAN_AMOUNT_TSONE = 0x00U, /*!< Tx one frame in STB */
    CAN_AMOUNT_TSALL = 0x01U  /*!< Tx all frame in STB */
} can_tsamount_t;

/*!
 * @brief CAN timestamp capture position
 */
typedef enum {
    CAN_TS_POS_SOF = 0x00U, /*!< Capture timestamp at SOF of a frame */
    CAN_TS_POS_EOF = 0x01U  /*!< Capture timestamp at EOF of a frame */
} can_timestamp_pos_t;

/*!
 * @brief CAN receive overflow mode
 */
typedef enum {
    CAN_ROM_OVERWRITE = 0x00U, /*!< Over write the oldest frame */
    CAN_ROM_DISCARD   = 0x01U  /*!< Discard the newest frame */
} can_rom_t;
/*******APIs*******************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif

/*!
 * @brief Set can mode
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] mode: Can mode
 * @return None
 */
void CAN_REG_SetMode(CAN_Type* regBase, can_mode_t mode);

/*!
 * @brief Set Can Tx message buffer
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] type: Buffer type
 *           - CAN_PRIMARY_TRANSMIT_BUFFER
 *           - CAN_SECONDARY_TRANSMIT_BUFFER
 * @param[in] info: Send message info
 * @param[in] msgId: Send message id
 * @param[in] data: Send message data
 * @return None
 */
void CAN_REG_SetTxMsg(CAN_Type* regBase,
                      can_buffer_type_t type,
                      const can_data_info_t* info,
                      uint32_t msgId,
                      const uint8_t* msgData);

/*!
 * @brief Read a message from receive buffer
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] data: Receive message buffer
 * @return None
 */
void CAN_REG_ReadRxFifo(CAN_Type* regBase, can_msgbuff_t* data);

/*!
 * @brief Set Can FD enable
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] enable: Enable/Disable CAN FD
 * @return None
 */
static inline void CAN_REG_SetFdEnable(CAN_Type* regBase, bool enable)
{
    uint32_t regValue = regBase->CTRL0 & (~(CAN_CTRL0_TSNEXT_Msk | CAN_CTRL0_TSALL_Msk | CAN_CTRL0_TSONE_Msk | CAN_CTRL0_TPE_Msk));

    regValue &= ~CAN_CTRL0_CANFDEN_Msk;
    regValue |= CAN_CTRL0_CANFDEN(enable ? 1UL : 0UL);

    regBase->CTRL0 = regValue;
}

/*!
 * @brief Trig message transmission
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] type: Buffer type
 *           - CAN_PRIMARY_TRANSMIT_BUFFER
 *           - CAN_SECONDARY_TRANSMIT_BUFFER
 * @param[in] amount: Transmission amount for STB
 *                    - CAN_AMOUNT_TSONE
*                     - CAN_AMOUNT_TSALL
 * @return None
 */
static inline void CAN_REG_TrigTx(CAN_Type* regBase, can_buffer_type_t type, can_tsamount_t amount)
{
    uint32_t regValue = regBase->CTRL0;

    if (type == CAN_PRIMARY_TRANSMIT_BUFFER) {
        regValue = ((regValue & (~(CAN_CTRL0_TSNEXT_Msk | CAN_CTRL0_TSALL_Msk  \
                                   | CAN_CTRL0_TSONE_Msk))) | CAN_CTRL0_TPE_Msk);
    } else {
        if (amount == CAN_AMOUNT_TSONE) {
            regValue = ((regValue & (~(CAN_CTRL0_TSNEXT_Msk | CAN_CTRL0_TPE_Msk))) \
                        | CAN_CTRL0_TSONE_Msk);
        } else {
            regValue = ((regValue & (~(CAN_CTRL0_TSNEXT_Msk | CAN_CTRL0_TPE_Msk))) \
                        | CAN_CTRL0_TSALL_Msk);
        }
    }

    regBase->CTRL0 = regValue;
}

/*!
 * @brief Set Can FD mode if Can FD is enable
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] enable: True for ISO mode and false for non-ISO(bosch) mode
 * @return None
 */
static inline void CAN_REG_SetFdIso(CAN_Type* regBase, bool enable)
{
    uint32_t regValue = regBase->CTRL0 & (~(CAN_CTRL0_TSNEXT_Msk | CAN_CTRL0_TSALL_Msk | CAN_CTRL0_TSONE_Msk | CAN_CTRL0_TPE_Msk));

    regValue &= ~CAN_CTRL0_FDISO_Msk;
    regValue |= CAN_CTRL0_FDISO(enable ? 1UL : 0UL);

    regBase->CTRL0 = regValue;
}

/*!
 * @brief Abort a transmit
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] type: buffer type
 *           - CAN_PRIMARY_TRANSMIT_BUFFER
 *           - CAN_SECONDARY_TRANSMIT_BUFFER
 * @return None
 */
static inline void CAN_REG_AbortTxMsg(CAN_Type* regBase, can_buffer_type_t type)
{
    if (type == CAN_PRIMARY_TRANSMIT_BUFFER) {
        regBase->CTRL0 |= CAN_CTRL0_TPA(1UL);
    } else {
        regBase->CTRL0 |= CAN_CTRL0_TSA(1UL);
    }
}
/*!
 * @brief Set filter for receiver
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] filterNum: Filter number, range 1~16, zero will cause no message received
 * @param[in] filterTable: Point to filter list
 * @return None
 */
static inline void CAN_REG_SetRxFilter(CAN_Type* regBase, uint32_t filterNum, const can_filter_config_t* filterTable)
{
    if (0 != (regBase->CTRL0 & CAN_CTRL0_RESET_Msk)) {

        uint32_t regValue = regBase->ACFCTRL0;
        regValue &= ~CAN_ACFCTRL0_ACFEN0_Msk;
        regValue |= CAN_ACFCTRL0_ACFEN0((1UL << filterNum) - 1UL);
        regBase->ACFCTRL0 = regValue;


#if CONFIG_CAN_MAX_FILTER_NUM > 16

        if (filterNum > 16) {
            regValue = regBase->ACFCTRL1;
            regValue &= ~CAN_ACFCTRL1_ACFEN1_Msk;
            regValue |= CAN_ACFCTRL1_ACFEN1((1UL << (filterNum - 16UL)) - 1UL);
            regBase->ACFCTRL1 = regValue;
        }

#endif

        for (uint32_t i = 0UL; i < filterNum; i++) {
            regBase->ACFCTRL0 = (regBase->ACFCTRL0 & ~CAN_ACFCTRL0_ACFADR_Msk) | CAN_ACFCTRL0_ACFADR(i);
            regBase->ACFCTRL0 &= ~CAN_ACFCTRL0_SELMASK_Msk;
            regBase->ACF = filterTable[i].code | (5UL << 29);
            regBase->ACFCTRL0 |= CAN_ACFCTRL0_SELMASK_Msk;

            if (i % 2 == 1) {
                regBase->ACF = filterTable[i].mask | (1UL << 31);
            } else {
                regBase->ACF = filterTable[i].mask;
                regBase->ACF &= ~(1UL << 31);
            }
        }
    }
}

/*!
 * @brief Set RESET reg
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] enable: State
 *            - true: Assert RESET
 *            - false: Deassert RESET
 * @return None
 */
static inline void CAN_REG_SetReset(CAN_Type* regBase, bool enable)
{
    uint32_t regValue = regBase->CTRL0 & (~(CAN_CTRL0_TSNEXT_Msk | CAN_CTRL0_TSALL_Msk | CAN_CTRL0_TSONE_Msk | CAN_CTRL0_TPE_Msk));

    regValue &= ~CAN_CTRL0_RESET_Msk;
    regValue |= CAN_CTRL0_RESET(enable ? 1UL : 0UL);

    regBase->CTRL0 = regValue;
}

/*!
 * @brief Check if the CAN is Reset status
 *
 * @param[in] regBase: The CAN register base address
 * @return true: On reset
 *         false: Not on reset.
 */
static inline bool CAN_REG_IsReset(CAN_Type* regBase)
{
    return (regBase->CTRL0 & CAN_CTRL0_RESET_Msk ? true : false);
}

/*!
 * @brief Set nominal bit rate
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] bitrate: Point to bit rate config data
 * @return None
 */
static inline void CAN_REG_SetBitrate(CAN_Type* regBase, const can_time_segment_t* bitrate)
{
    if (0 != (regBase->CTRL0 & CAN_CTRL0_RESET_Msk)) {
        uint32_t regValue = 0UL;

        regValue |= CAN_SBITRATE_S_PRESC(bitrate->prescaler);
        regValue |= CAN_SBITRATE_S_SEG_1(bitrate->phaseSeg1);
        regValue |= CAN_SBITRATE_S_SEG_2(bitrate->phaseSeg2);
        regValue |= CAN_SBITRATE_S_SJW(bitrate->rJumpwidth);

        regBase->SBITRATE = regValue;
    }
}

/*!
 * @brief Get nominal bit rate config
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] bitrate: Point to bit rate config data
 * @return None
 */
static inline void CAN_REG_GetBitrate(CAN_Type* regBase, can_time_segment_t* bitrate)
{
    uint32_t regValue = regBase->SBITRATE;

    bitrate->prescaler = (regValue & CAN_SBITRATE_S_PRESC_Msk) >> CAN_SBITRATE_S_PRESC_Pos;
    bitrate->phaseSeg1 = (regValue & CAN_SBITRATE_S_SEG_1_Msk) >> CAN_SBITRATE_S_SEG_1_Pos;
    bitrate->phaseSeg2 = (regValue & CAN_SBITRATE_S_SEG_2_Msk) >> CAN_SBITRATE_S_SEG_2_Pos;
    bitrate->rJumpwidth = (regValue & CAN_SBITRATE_S_SJW_Msk) >> CAN_SBITRATE_S_SJW_Pos;
}

/*!
 * @brief Set CAN FD bit rate
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] bitrate: Point to bit rate config data
 * @return None
 */
static inline void CAN_REG_SetBitrateFD(CAN_Type* regBase, const can_time_segment_t* bitrate)
{
    if (0 != (regBase->CTRL0 & CAN_CTRL0_RESET_Msk)) {
        uint32_t regValue = 0;

        regValue |= CAN_FBITRATE_f_PRESC(bitrate->prescaler);
        regValue |= CAN_FBITRATE_f_SEG_1(bitrate->phaseSeg1);
        regValue |= CAN_FBITRATE_f_SEG_2(bitrate->phaseSeg2);
        regValue |= CAN_FBITRATE_f_SJW(bitrate->rJumpwidth);

        regBase->FBITRATE = regValue;
    }
}

/*!
 * @brief Get CAN FD bit rate config
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] bitrate: Point to bit rate config data
 * @return None
 */
static inline void CAN_REG_GetBitrateFD(CAN_Type* regBase, can_time_segment_t* bitrate)
{
    uint32_t regValue = regBase->FBITRATE;

    bitrate->prescaler = (regValue & CAN_FBITRATE_f_PRESC_Msk) >> CAN_FBITRATE_f_PRESC_Pos;
    bitrate->phaseSeg1 = (regValue & CAN_FBITRATE_f_SEG_1_Msk) >> CAN_FBITRATE_f_SEG_1_Pos;
    bitrate->phaseSeg2 = (regValue & CAN_FBITRATE_f_SEG_2_Msk) >> CAN_FBITRATE_f_SEG_2_Pos;
    bitrate->rJumpwidth = (regValue & CAN_FBITRATE_f_SJW_Msk) >> CAN_FBITRATE_f_SJW_Pos;
}

/*!
 * @brief Set interrupt
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] mask: Mask of INTE register
 * @param[in] enable: Enable/Disable interrupt
 * @return None
 */
static inline void CAN_REG_SetInt(CAN_Type* regBase, uint32_t mask, bool enable)
{
    uint32_t regValue = regBase->CTRL1;

    if (enable) {
        regValue |= (mask & CAN_INT_EN_Msk);
    } else {
        regValue &= ~(mask & CAN_INT_EN_Msk);
    }

    regBase->CTRL1 = regValue;
}

/*!
 * @brief Get interrupt
 *
 * @param[in] regBase: The CAN register base address
 * @return Interrupt register value from INTE
 */
static inline uint32_t CAN_REG_GetInt(CAN_Type* regBase)
{
    return regBase->CTRL1 & CAN_INT_EN_Msk;
}

/*!
 * @brief Get interrupt flag
 *
 * @param[in] regBase: The CAN register base address
 * @return Interrupt flag register value from INTF
 */
static inline uint32_t CAN_REG_GetIntFlag(CAN_Type* regBase)
{
    return regBase->CTRL1 & CAN_INT_FLAG_Msk;
}

/*!
 * @brief Clear interrupt flag
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] flag: Flag to be cleared
 * @return None
 */
static inline void CAN_REG_ClearIntFlag(CAN_Type* regBase, uint32_t flag)
{
    uint32_t regValue = regBase->CTRL1;

    regValue &= ~CAN_INT_FLAG_Msk;
    regValue |= (flag & CAN_INT_FLAG_Msk);

    regBase->CTRL1 = regValue;
}

/*!
 * @brief Set TDC
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] enable: Enable/Disable TDC
 * @param[in] offset: TDC offset value if TDC is enable
 * @return None
 */
static inline void CAN_REG_SetTDCOffset(CAN_Type* regBase, bool enable, uint8_t offset)
{
    if (0 != (regBase->CTRL0 & CAN_CTRL0_RESET_Msk)) {
        uint32_t regValue = regBase->ERRINFO;

        if (enable) {
            regValue |= CAN_ERRINFO_TDCEN(1UL);
            regValue &= ~CAN_ERRINFO_SSPOFF_Msk;
            regValue |= CAN_ERRINFO_SSPOFF(offset);
        } else {
            regValue &= ~CAN_ERRINFO_TDCEN_Msk;
        }

        regBase->ERRINFO = regValue;
    }
}

/*!
 * @brief Get TDC offset value
 *
 * @param[in] regBase: The CAN register base address
 * @return TDC offset value
 */
static inline uint8_t CAN_REG_GetTDCOffset(CAN_Type* regBase)
{
    return (uint8_t)((regBase->ERRINFO & CAN_ERRINFO_SSPOFF_Msk) >> CAN_ERRINFO_SSPOFF_Pos);
}

/*!
 * @brief Set CAN busoff recovery

 * @param[in] regBase: The CAN register base address
 * @param[in] enable: true : Enable/Disable auto recovery
 * @return None
 */
static inline void CAN_REG_SetBorec(CAN_Type* regBase, bool enable)
{
    uint32_t regValue = regBase->CTRL0 & (~(CAN_CTRL0_TSNEXT_Msk | CAN_CTRL0_TSALL_Msk | CAN_CTRL0_TSONE_Msk | CAN_CTRL0_TPE_Msk));

    regValue &= ~CAN_CTRL0_BOFFREC_Msk;
    regValue |= CAN_CTRL0_BOFFREC(enable ? 0UL : 1UL);

    regBase->CTRL0 = regValue;
}

/*!
 * @brief Set CAN timestamp

 * @param[in] regBase: The CAN register base address
 * @param[in] enable: true : Enable/Disable timestamp
 * @param[in] pos: Timestamp capture postion
 *            - CAN_TS_POS_SOF : Capture at start of frame
 *            - CAN_TS_POS_EOF : Capture at end of frame
 * @return None
 */
static inline void CAN_REG_SetTimestamp(CAN_Type* regBase, bool enable, can_timestamp_pos_t pos)
{
    uint32_t regValue = regBase->ACFCTRL0;

    if (enable) {
        regValue |= CAN_ACFCTRL0_TIMEEN(1UL);
        regValue &= ~CAN_ACFCTRL0_TIMEPOS_Msk;
        regValue |= CAN_ACFCTRL0_TIMEPOS((pos == CAN_TS_POS_SOF) ? 0UL : 1UL);
    } else {
        regValue &= ~CAN_ACFCTRL0_TIMEEN_Msk;
    }

    regBase->ACFCTRL0 = regValue;
}

/*!
 * @brief Get Can TEC
 *
 * @param[in] regBase: The CAN register base address
 * @return TEC value
 */
static inline uint8_t CAN_REG_GetTEC(CAN_Type* regBase)
{
    return (uint8_t)((regBase->ERRINFO & CAN_ERRINFO_TECNT_Msk) >> CAN_ERRINFO_TECNT_Pos);
}

/*!
 * @brief Get Can REC
 *
 * @param[in] regBase: The CAN register base address
 * @return REC value
 */
static inline uint8_t CAN_REG_GetREC(CAN_Type* regBase)
{
    return (uint8_t)((regBase->ERRINFO & CAN_ERRINFO_RECNT_Msk) >> CAN_ERRINFO_RECNT_Pos);
}

/*!
 * @brief Get Can Rx fifo status
 *
 * @param[in] regBase: The CAN register base address
 * @return Register value of reg RSTAT
 */
static inline uint8_t CAN_REG_GetRSTAT(CAN_Type* regBase)
{
    return (uint8_t)((regBase->CTRL0 & CAN_CTRL0_RSTAT_Msk) >> CAN_CTRL0_RSTAT_Pos);
}

/*!
 * @brief Get Can KOER register
 *
 * @param[in] regBase: The CAN register base address
 * @return Register value of reg KOER
 */
static inline uint8_t CAN_REG_GetKOER(CAN_Type* regBase)
{
    return (uint8_t)((regBase->ERRINFO & CAN_ERRINFO_KOER_Msk) >> CAN_ERRINFO_KOER_Pos);
}

/*!
 * @brief Set self ack feature
 *
 * @note Only use for LBME = 1, if enabled, CAN module is allowed to receive frames
 *       transmitted by itself
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] enable: Enable/Disable self reception
 * @return None
 */
static inline void CAN_REG_SetSelfAck(CAN_Type* regBase, bool enable)
{
    uint32_t regValue = regBase->CTRL0 & (~(CAN_CTRL0_TSNEXT_Msk | CAN_CTRL0_TSALL_Msk | CAN_CTRL0_TSONE_Msk | CAN_CTRL0_TPE_Msk));

    regValue &= ~CAN_CTRL0_SACK_Msk;
    regValue |= CAN_CTRL0_SACK(enable ? 1 : 0);

    regBase->CTRL0 = regValue;
}

/*!
 * @brief Set receive overflow mode
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] rom: Receive overflow mode
 *            - CAN_ROM_OVERWRITE : New frame over write the oldest frame
 *            - CAN_ROM_DISCARD : New frame is discarded
 * @return None
 */
static inline void CAN_REG_SetRom(CAN_Type* regBase, can_rom_t rom)
{
    uint32_t regValue = regBase->CTRL0 & (~(CAN_CTRL0_TSNEXT_Msk | CAN_CTRL0_TSALL_Msk | CAN_CTRL0_TSONE_Msk | CAN_CTRL0_TPE_Msk));

    regValue &= ~CAN_CTRL0_ROM_Msk;
    regValue |= CAN_CTRL0_ROM((rom == CAN_ROM_DISCARD) ? 1 : 0);

    regBase->CTRL0 = regValue;
}

/*!
 * @brief Check busoff status
 *
 * @param[in] regBase: The CAN register base address
 * @return true CAN is busoff
 *         false CAN is not busoff
 */
static inline bool CAN_REG_IsBusoff(CAN_Type* regBase)
{
    return ((regBase->CTRL0 & CAN_CTRL0_BUSOFF_Msk) ? true : false);
}

/*!
 * @brief Check transmit buffer is empty
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] type: Buffer type
 *           - CAN_PRIMARY_TRANSMIT_BUFFER
 *           - CAN_SECONDARY_TRANSMIT_BUFFER
 * @return true: Empty
 *         false: Not empty
 */
static inline bool CAN_REG_IsTransmitBuffEmpty(CAN_Type* regBase, can_buffer_type_t type)
{
    bool result;

    if (type == CAN_PRIMARY_TRANSMIT_BUFFER) {
        result = (regBase->CTRL0 & CAN_CTRL0_TPE_Msk) ? false : true;
    } else {
        result = (regBase->CTRL0 & CAN_CTRL0_TSSTAT_Msk) ? false : true;
    }

    return result;
}

/*!
 * @brief Check transmit buffer is full
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] type: Buffer type
 *           - CAN_PRIMARY_TRANSMIT_BUFFER
 *           - CAN_SECONDARY_TRANSMIT_BUFFER
 * @return true: Full
 *         false: Not full
 */
static inline bool CAN_REG_IsTransmitBuffFull(CAN_Type* regBase, can_buffer_type_t type)
{
    bool result;

    if (type == CAN_PRIMARY_TRANSMIT_BUFFER) {
        result = (regBase->CTRL0 & CAN_CTRL0_TPE_Msk) ? true : false;
    } else {
        result = ((regBase->CTRL0 & CAN_CTRL0_TSSTAT_Msk) == CAN_CTRL0_TSSTAT_Msk) ? true : false;
    }

    return result;
}

/*!
 * @brief Check buffer is transmitting
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] type: Buffer type
 *           - CAN_PRIMARY_TRANSMIT_BUFFER
 *           - CAN_SECONDARY_TRANSMIT_BUFFER
 * @return true: Is transmitting
 *         false: Is idle
 */
static inline bool CAN_REG_IsTransmitting(CAN_Type* regBase, can_buffer_type_t type)
{
    bool result;

    if (type == CAN_PRIMARY_TRANSMIT_BUFFER) {
        result = (regBase->CTRL0 & CAN_CTRL0_TPE_Msk) ? true : false;
    } else {
        result = ((regBase->CTRL0 & (CAN_CTRL0_TSALL_Msk | CAN_CTRL0_TSONE_Msk)) != 0) ? true : false;
    }

    return result;
}

/*!
 * @brief Check rx fifo is empty
 *
 * @param[in] regBase: The CAN register base address
 * @return true: Empty
 *         false: Not Empty
 * @return None
 */
static inline bool CAN_REG_IsRxFifoEmpty(CAN_Type* regBase)
{
    return (((regBase->CTRL0 & CAN_CTRL0_RSTAT_Msk) >> CAN_CTRL0_RSTAT_Pos) == 0) ? true : false;
}

/*!
 * @brief Set Can receive almost full warning value
 *
 * @param[in] regBase: The CAN register base address
 * @param[in] warnValue:  receive almost full warning value of CAN moudle
 * @return None
 */
static inline void CAN_REG_SetAFWL(CAN_Type* regBase, uint32_t warnValue)
{
    uint32_t regValue = regBase->CTRL1;

    regValue &= ~CAN_CTRL1_AFWL_Msk;
    regValue |= CAN_CTRL1_AFWL(warnValue);

    regBase->CTRL1 = regValue;
}

/*!
 * @brief Get CAN CTRL0 value
 *
 * @param[in] regBase: The CAN register base address
 * @return regValue: The value of CAN CTRL0
 */
static inline uint32_t CAN_REG_GetCtrl0(CAN_Type* regBase)
{
    uint32_t regValue = regBase->CTRL0;

    return regValue;
}

/*!
 * @brief Get CAN passive error status
 *
 * @param[in] regBase: The CAN register base address
 * @return : passive error status
 */
static inline bool CAN_REG_GetPassiveStauts(CAN_Type* regBase)
{
    return ((regBase->CTRL1 & CAN_CTRL1_EPASS_Msk) >> CAN_CTRL1_EPASS_Pos) == 1 ? true : false;
}

#if defined(__cplusplus)
}
#endif

#endif /* CAN_REG_ACCESS_H */

/*******EOF********************************************************************/
